from typing import Callable, Dict, Any, Optional, Set
from .generic import build_body as build_generic

# 指令信息统一管理
# 格式：{指令ID: {'name': 名称, 'type': 类型, 'reply': 回复指令ID}}
_FRAME_INFO = {
    0x0001: {'name': '终端通用应答', 'type': 'reply'},
    0x0100: {'name': '终端注册', 'type': 'query', 'reply': 0x8100},
    0x0102: {'name': '终端鉴权', 'type': 'data'},
    0x0104: {'name': '查询终端参数应答', 'type': 'reply'},
    0x0107: {'name': '查询终端属性应答', 'type': 'reply'},
    0x010e: {'name': '终端故障代码应答', 'type': 'reply'},
    0x0200: {'name': '位置信息上报', 'type': 'data'},
    0x0704: {'name': '定位数据批量上传', 'type': 'data'},
    0x8001: {'name': '平台通用应答', 'type': 'reply'},
    0x8100: {'name': '终端注册应答', 'type': 'reply'},
    0x8103: {'name': '设置终端参数', 'type': 'query'},
    0x8104: {'name': '查询终端参数', 'type': 'query', 'reply': 0x0104},
    0x8106: {'name': '查询指定终端参数', 'type': 'query', 'reply': 0x0104},
    0x8105: {'name': '终端控制', 'type': 'query'},
    0x8107: {'name': '查询终端属性', 'type': 'query', 'reply': 0x0107},
    0x8108: {'name': '下发终端升级包', 'type': 'query'},
    0x810e: {'name': '查询终端故障代码', 'type': 'query', 'reply': 0x010e},
    0x9003: {'name': '终端上传音视频属性', 'type': 'data', 'reply': 0x1003},
    0x1003: {'name': '终端上传音视频属性应答', 'type': 'data'},
    0x0108: {'name': '终端升级结果应答', 'type': 'reply'},
    0x8110: {'name': '设置驾驶员人脸信息', 'type': 'query'},
    0x8111: {'name': '删除驾驶员人脸信息', 'type': 'query'},
    0x8112: {'name': '查询驾驶员人脸列表信息', 'type': 'query', 'reply': 0x0112},
    0x0112: {'name': '查询驾驶员人脸列表信息应答', 'type': 'reply'},
    0x8202: {'name': '临时位置跟踪控制', 'type': 'query'},
    0x8203: {'name': '人工确认报警消息', 'type': 'query'},
    0x8700: {'name': '行驶记录数据采集命令', 'type': 'query'},
    0x0700: {'name': '行驶记录数据上传', 'type': 'reply', 'reply': 0x8700},
    0x8701: {'name': '行驶记录参数下传命令', 'type': 'query'},
    0x0701: {'name': '电子运单上报', 'type': 'data'},
    0x8702: {'name': '上报驾驶员身份信息请求', 'type': 'query'},
    0x0702: {'name': '驾驶员身份信息采集上报', 'type': 'reply', 'reply': 0x8702},
    0x8300: {'name': '文本信息下发', 'type': 'query'},
    0x8400: {'name': '电话回拨', 'type': 'query'},
    0x8401: {'name': '设置电话本', 'type': 'query'},
    0x9209: {'name': '附件上传请求', 'type': 'query'},
    0x1213: {'name': '附件上传完成消息', 'type': 'data'},
    0x1005: {'name': '终端上传乘客流量', 'type': 'data'},
}

# 自动推导的查询-回复关系
_QUERY_REPLY_MAPPING = {k: v['reply'] for k, v in _FRAME_INFO.items() if v.get('type') == 'query' and 'reply' in v}
_REPLY_QUERY_MAPPING = {v: k for k, v in _QUERY_REPLY_MAPPING.items()}


def get_frame_builder(frame_id: int) -> Callable:
    if frame_id not in _FRAME_INFO:
        raise ValueError(f'不支持的帧ID: 0x{frame_id:04x}')
    return build_generic


def parse_body_generic(common: Dict[str, Any], frame_cfg: Dict[str, Any], state: Dict[str, Any], body_bytes: bytes) -> Dict[str, Any]:
    from protocol.decoder import decode_field
    # 直接使用 frame_cfg 作为解码配置
    result, _ = decode_field(body_bytes, 0, frame_cfg, path=['body'])
    return result


def parse_body_0x0704(common: Dict[str, Any], frame_cfg: Dict[str, Any], state: Dict[str, Any], body_bytes: bytes) -> Dict[str, Any]:
    """0x0704批量上传的专用解析器，处理dataCount和locationType字段"""
    from protocol.decoder import decode_field
    import struct

    if len(body_bytes) < 3:
        raise ValueError('0x0704消息体长度不足')

    # 读取dataCount (WORD, 2 bytes)
    data_count = struct.unpack('>H', body_bytes[0:2])[0]

    # 读取locationType (BYTE, 1 byte)
    location_type = body_bytes[2]

    # 构建临时配置来解析位置数据列表
    location_list_cfg = frame_cfg['fields'][1]  # locationDataList配置

    # 解析每个位置数据项
    items = []
    offset = 3  # 跳过dataCount和locationType

    for i in range(data_count):
        # 使用单个元素配置解析
        item_cfg = {
            'type': 'STRUCT',
            'fields': location_list_cfg['fields']
        }
        item_data, new_offset = decode_field(body_bytes, offset, item_cfg, path=['body', 'locationDataList', f'[{i}]'])
        items.append(item_data)
        offset = new_offset

    return {
        'locationType': location_type,
        'locationDataList': items
    }


def get_frame_parser(frame_id: int) -> Callable:
    if frame_id not in _FRAME_INFO:
        raise ValueError(f'不支持的帧ID: 0x{frame_id:04x}')
    # 0x0704使用专用解析器
    if frame_id == 0x0704:
        return parse_body_0x0704
    return parse_body_generic


def get_frame_info(frame_id: int) -> Optional[Dict[str, Any]]:
    """
    获取指令信息
    
    Args:
        frame_id: 指令ID
        
    Returns:
        指令信息字典，如果不存在则返回None
    """
    return _FRAME_INFO.get(frame_id)


def get_reply_for_query(query_id: int) -> Optional[int]:
    """获取查询指令对应的回复指令ID"""
    return _QUERY_REPLY_MAPPING.get(query_id)


def get_query_for_reply(reply_id: int) -> Optional[int]:
    """获取回复指令对应的查询指令ID"""
    return _REPLY_QUERY_MAPPING.get(reply_id)


def is_query_frame(frame_id: int) -> bool:
    """判断是否为查询指令"""
    return _FRAME_INFO.get(frame_id, {}).get('type') == 'query'


def is_reply_frame(frame_id: int) -> bool:
    """判断是否为回复指令"""
    return _FRAME_INFO.get(frame_id, {}).get('type') == 'reply'


def is_data_frame(frame_id: int) -> bool:
    """判断是否为数据指令"""
    return _FRAME_INFO.get(frame_id, {}).get('type') == 'data'


def get_supported_frame_ids() -> Set[int]:
    """获取所有支持的指令ID"""
    return set(_FRAME_INFO.keys())


def is_supported_frame(frame_id: int) -> bool:
    """判断指令ID是否被支持"""
    return frame_id in _FRAME_INFO


def get_query_reply_pairs() -> Dict[int, int]:
    """获取所有查询-回复关系对"""
    return _QUERY_REPLY_MAPPING.copy()


def add_frame(frame_id: int, name: str, frame_type: str, reply_id: Optional[int] = None) -> None:
    """
    添加新的指令信息
    
    Args:
        frame_id: 指令ID
        name: 指令名称
        frame_type: 指令类型 ('query', 'reply', 'data')
        reply_id: 回复指令ID（仅查询指令需要）
    """
    info = {'name': name, 'type': frame_type}
    if reply_id is not None:
        info['reply'] = reply_id
    _FRAME_INFO[frame_id] = info
    
    # 重新计算查询-回复关系
    global _QUERY_REPLY_MAPPING, _REPLY_QUERY_MAPPING
    _QUERY_REPLY_MAPPING = {k: v['reply'] for k, v in _FRAME_INFO.items() if v.get('type') == 'query' and 'reply' in v}
    _REPLY_QUERY_MAPPING = {v: k for k, v in _QUERY_REPLY_MAPPING.items()}

